import pygame, sys, random, time, copy

#常量
from pygame.locals import *
UP, DOWN, LEFT, RIGHT = '向上', '向下', '向左', '向右'
#               R    G    B
WHITE       = (255, 255, 255)
BLACK       = (  0,   0,   0)
GREEN       = (  0, 155,   0)
BRIGHTBLUE  = (  0,  50, 255)
BROWN       = (174,  94,   0)
BGCOLOR = GREEN
GRIDCOLOR = BLACK
TEXTCOLOR = WHITE
TEXTBGCOLOR = BRIGHTBLUE
FPS = 10
WINDOWWIDTH = 800
WINDOWHEIGHT = 600
SPACESIZE = 50
BOARDWIDTH = 8
BOARDHEIGHT = 8
XMARGIN = (WINDOWWIDTH - SPACESIZE*BOARDWIDTH) // 2
YMARGIN = (WINDOWHEIGHT - SPACESIZE*BOARDHEIGHT) // 2
WHITE_TILE = '白子'
BLACK_TILE = '黑子'
EMPTY_SPACE = '空格'
ANIMATIONSPEED = 25
WINDOWCAPTION = '翻棋子'
FONTFILENAME = 'res/msyh.ttc'
FONTSIZE = 20
ICONFILENAME = 'res/gameicon.png'
SOUNDFILENAME = 'res/gamesound.mp3'
#终止程序
def terminate():
    pygame.quit()
    sys.exit()
#关闭窗口或按Esc键退出程序
def checkForQuit():
    for event in pygame.event.get(QUIT):
        terminate()
    for event in pygame.event.get(KEYUP):
        if event.key == K_ESCAPE:
            terminate()
        else:
            pygame.event.post(event)
def getNewBoard():
    board = []
    for i in range(BOARDWIDTH):
        board.append([EMPTY_SPACE] * BOARDHEIGHT)
    return board
def resetBoard(board):
    for x in range(BOARDWIDTH):
        for y in range(BOARDHEIGHT):
            board[x][y] = EMPTY_SPACE
    x, y = BOARDWIDTH//2, BOARDHEIGHT//2
    board[x][y] = WHITE_TILE
    board[x][y-1] = BLACK_TILE
    board[x-1][y] = BLACK_TILE
    board[x-1][y-1] = WHITE_TILE
def drawBoard(board):
    DISPLAYSURFACE.fill(BGCOLOR)
    #画棋盘的竖线
    for x in range(BOARDWIDTH + 1):
        startx = (SPACESIZE * x) + XMARGIN
        starty = YMARGIN
        endx = (SPACESIZE * x) + XMARGIN
        endy = YMARGIN + (SPACESIZE * BOARDHEIGHT)
        pygame.draw.line(DISPLAYSURFACE, GRIDCOLOR, (startx, starty), (endx, endy))
    #画棋盘的横线
    for y in range(BOARDHEIGHT + 1):
        startx = XMARGIN
        starty = YMARGIN + (SPACESIZE * y)
        endx = XMARGIN + (SPACESIZE * BOARDWIDTH)
        endy = YMARGIN + (SPACESIZE * y)
        pygame.draw.line(DISPLAYSURFACE, GRIDCOLOR, (startx, starty), (endx, endy))
    #画棋子
    for x in range(BOARDWIDTH):
        for y in range(BOARDHEIGHT):
            centerx, centery = translateBoardToPixelCoord(x, y)
            if board[x][y] != EMPTY_SPACE:
                if board[x][y] == WHITE_TILE:
                    tileColor = WHITE
                elif board[x][y] == BLACK_TILE:
                    tileColor = BLACK
                pygame.draw.circle(DISPLAYSURFACE, tileColor, (centerx, centery), SPACESIZE//2-4)
def translateBoardToPixelCoord(x, y):
    return XMARGIN + SPACESIZE*x + SPACESIZE//2, YMARGIN + SPACESIZE*y + SPACESIZE//2
def getSpaceClicked(mousexy):
    mousex, mousey = mousexy
    for x in range(BOARDWIDTH):
        for y in range(BOARDHEIGHT):
            if mousex > SPACESIZE*x + XMARGIN and \
               mousex < SPACESIZE*(x+1) + XMARGIN and \
               mousey > SPACESIZE*y + YMARGIN and \
               mousey < SPACESIZE*(y+1) + YMARGIN :
                return x, y
    return None
def isOnBoard(x, y):
    return x >= 0 and x < BOARDWIDTH and y >= 0 and y < BOARDHEIGHT
def isOnCorner(x, y):
    return x == 0 and y == 0 or \
           x == BOARDWIDTH-1 and y == 0 or \
           x == 0 and y == BOARDHEIGHT-1 or \
           x == BOARDWIDTH-1 and y == BOARDHEIGHT-1

def isValidMove(board, tile, movexy):
    xstart, ystart = movexy
    if board[xstart][ystart] != EMPTY_SPACE or \
       not isOnBoard(xstart, ystart):
        return False
    board[xstart][ystart] = tile
    if tile == WHITE_TILE:
        otherTile = BLACK_TILE
    else:
        otherTile = WHITE_TILE
    tilesToFlip = []
    for xdirection, ydirection in [[0,1], [1,1], [1,0], [1,-1], [0,-1], [-1,-1], [-1,0], [-1,1]]:
        x, y = xstart, ystart
        x += xdirection
        y += ydirection
        if isOnBoard(x, y) and board[x][y] == otherTile:
            x += xdirection
            y += ydirection
            if not isOnBoard(x, y):
                continue
            while board[x][y] == otherTile:
                x += xdirection
                y += ydirection
                if not isOnBoard(x, y):
                    break
            if not isOnBoard(x, y):
                continue
            if board[x][y] == tile:
                while True:
                    x -= xdirection
                    y -= ydirection
                    if x == xstart and y ==  ystart:
                        break
                    tilesToFlip.append([x, y])
    board[xstart][ystart] = EMPTY_SPACE
    if len(tilesToFlip) == 0:
        return False
    return tilesToFlip
def makeMove(board, tile, movexy, realMove=False):
    xstart, ystart = movexy
    tilesToFlip = isValidMove(board, tile, movexy)
    if tilesToFlip == False:
        return False
    board[xstart][ystart] = tile
    for x, y in tilesToFlip:
        board[x][y] = tile
    return True
def getValidMoves(board, tile):
    validMoves = []
    for x in range(BOARDWIDTH):
        for y in range(BOARDHEIGHT):
            movexy = (x, y)
            if isValidMove(board, tile, movexy):
                validMoves.append(movexy)
    return validMoves
def getComputerMove(board, computerTile):
    possibleMoves = getValidMoves(board, computerTile)
    random.shuffle(possibleMoves)
    for x, y in possibleMoves:
        if isOnCorner(x, y):
            return [x, y]
    bestScore = -1
    for x, y in possibleMoves:
        dupeBoard = copy.deepcopy(board)
        makeMove(dupeBoard, computerTile, [x, y])
        score = getScoreOfBoard(dupeBoard)[computerTile]
        if score > bestScore:
            bestMove = [x, y]
            bestScore = score
    return bestMove
def getScoreOfBoard(board):
    score={WHITE_TILE:0, BLACK_TILE:0}
    for x in range(BOARDWIDTH):
        for y in range(BOARDHEIGHT):
            if board[x][y] == WHITE_TILE:
                score[WHITE_TILE] += 1
            elif board[x][y] == BLACK_TILE:
                score[BLACK_TILE] += 1
    return score
def runGame():
    score, helpMode, gameIsOver = 0, True, False
    mouseDownPosition, mouseUpPosition = None, None
    playerTile, computerTile = BLACK_TILE, WHITE_TILE
    mainBoard = getNewBoard()
    resetBoard(mainBoard)
    turn = random.choice(['player', 'computer'])
    while True:
        #所有内容绘制到屏幕
        drawBoard(mainBoard)
        pygame.display.update()
        FPSCLOCK.tick(FPS)  
        
        if turn == 'player':
            if getValidMoves(mainBoard, playerTile) == []: #无可放棋子的地方了，本轮游戏结束
                break
            movexy = None
            while movexy == None:
                checkForQuit()#检查来自鼠标或键盘的退出事件，结束程序        
                #检测鼠标动作和键盘操作事件，进行登记或直接处理
                for event in pygame.event.get():
                    if event.type == MOUSEBUTTONUP:
                        mouseUpPosition = event.pos
                        movexy = getSpaceClicked(mouseUpPosition)
                        if movexy != None :
                            if not isValidMove(mainBoard, playerTile, movexy):
                                movexy = None
            makeMove(mainBoard, playerTile, movexy, True)
            turn = 'computer'
        else:
            if getValidMoves(mainBoard, computerTile) == []: #无可放棋子的地方了，本轮游戏结束
                break
            #暂停一段时间，让玩家看清楚变化，感觉计算机在思考
            pauseUntil = time.time() + random.randint(5, 15) * 0.1
            while time.time() < pauseUntil:
                pygame.display.update()
                
            movexy = getComputerMove(mainBoard, computerTile)
            makeMove(mainBoard, computerTile, movexy, True)
            turn = 'player'
    scores = getScoreOfBoard(mainBoard)
    if scores[playerTile] < scores[computerTile]:
        text = '计算机赢'
    elif scores[playerTile] > scores[computerTile]:
        text = '玩家赢'
    else:
        text = '平局'
    textSurf = BASICFONT.render(text, True, TEXTCOLOR, TEXTBGCOLOR)
    textRect = textSurf.get_rect()
    textRect.center = (WINDOWWIDTH//2, WINDOWHEIGHT//2)
    
    while True:
        checkForQuit()
        for event in pygame.event.get():
            if event.type == MOUSEBUTTONUP:
                mouseUpPosition = event.pos
                if textRect.collidepoint(mouseUpPosition):
                    return
        DISPLAYSURFACE.blit(textSurf, textRect)
        pygame.display.update()
        FPSCLOCK.tick(FPS) 
def flippy():
    #初始化    
    global DISPLAYSURFACE, FPSCLOCK, BASICFONT, BASICSOUND
    pygame.init()
    FPSCLOCK = pygame.time.Clock()
    DISPLAYSURFACE = pygame.display.set_mode((WINDOWWIDTH, WINDOWHEIGHT), 0, 32)
    pygame.display.set_caption(WINDOWCAPTION)
    pygame.display.set_icon(pygame.image.load(ICONFILENAME))    
    BASICFONT = pygame.font.Font(FONTFILENAME, FONTSIZE)
    BASICSOUND = pygame.mixer.Sound(SOUNDFILENAME)
    while True:
        runGame()
  
if __name__ == '__main__':
    flippy()